﻿//using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Windows.Forms;
using FormCommon;
using System.Drawing;
using HRM.Common.Properties;
//using NHTC.DataAccess;

public class TextBoxHandle
{
    private FormBase m_Form;
    private TextBox withEventsField_m_objTextBox;
    private TextBox m_objTextBox
    {
        get { return withEventsField_m_objTextBox; }
        set
        {
            if (withEventsField_m_objTextBox != null)
            {
                withEventsField_m_objTextBox.Enter -= objTextBox_Enter;
                withEventsField_m_objTextBox.KeyPress -= TextBox_KeyPress;
                withEventsField_m_objTextBox.MouseEnter -= objTextBox_MouseEnter;
                withEventsField_m_objTextBox.MouseLeave -= objTextBox_MouseLeave;
                withEventsField_m_objTextBox.PreviewKeyDown -= objTextBox_PreviewKeyDown;
                withEventsField_m_objTextBox.TextChanged -= objTextBox_TextChanged;
                withEventsField_m_objTextBox.LostFocus -= m_objTextBox_LostFocus;
                withEventsField_m_objTextBox.Validating -= TextBox_Validating;
                withEventsField_m_objTextBox.VisibleChanged -= objTextBox_VisibleChanged;
                withEventsField_m_objTextBox.ReadOnlyChanged -= m_objTextBox_ReadOnlyChanged;
                withEventsField_m_objTextBox.EnabledChanged -= m_objTextBox_EnabledChanged;
                withEventsField_m_objTextBox.LocationChanged -= m_objTextBox_LocationChanged;
            }
            withEventsField_m_objTextBox = value;
            if (withEventsField_m_objTextBox != null)
            {
                withEventsField_m_objTextBox.Enter += objTextBox_Enter;
                withEventsField_m_objTextBox.KeyPress += TextBox_KeyPress;
                withEventsField_m_objTextBox.MouseEnter += objTextBox_MouseEnter;
                withEventsField_m_objTextBox.MouseLeave += objTextBox_MouseLeave;
                withEventsField_m_objTextBox.PreviewKeyDown += objTextBox_PreviewKeyDown;
                withEventsField_m_objTextBox.TextChanged += objTextBox_TextChanged;
                withEventsField_m_objTextBox.LostFocus += m_objTextBox_LostFocus;
                withEventsField_m_objTextBox.Validating += TextBox_Validating;
                withEventsField_m_objTextBox.VisibleChanged += objTextBox_VisibleChanged;
                withEventsField_m_objTextBox.ReadOnlyChanged += m_objTextBox_ReadOnlyChanged;
                withEventsField_m_objTextBox.EnabledChanged += m_objTextBox_EnabledChanged;
                withEventsField_m_objTextBox.LocationChanged += m_objTextBox_LocationChanged;
            }
        }
    }
    private string m_sDataType;
    private object m_objMaxValue;
    private object m_objMinValue;
    private bool m_bClearError;

    private bool m_bMouseOver;
    private const string CS_FLOAT_TYPE = "NUMBER,DOUBLE,FLOAT,DECIMAL,MONEY,";
    private const string CS_INT_TYPE = "LONG,BIGINT,INT,INTEGER,SHORT,SMALLINT,";
    private const string CS_DATE_TYPE = "DATE,DATETIME,DATESHORT,";
    private const string CS_TIME_TYPE = "TIME,TIMEEX,";

    private const string CS_STRING_TYPE = "NVARCHAR2,VARCHAR2,VARCHAR,NVARCHAR,CHAR,NCLOB,TEXT,NTEXT,EMAIL,WEB,REGEX,";
    private string m_sAll_Data_Type = CS_FLOAT_TYPE + CS_INT_TYPE + CS_DATE_TYPE + CS_TIME_TYPE + CS_STRING_TYPE;

    private string m_sNumber_Data_Type = CS_FLOAT_TYPE + CS_INT_TYPE;

    private Button btnCalendar;

    protected TextBoxHandle()
    {
    }

    public object MaxValue
    {
        get { return m_objMaxValue; }
        set { m_objMaxValue = value; }
    }

    public object MinValue
    {
        get { return m_objMinValue; }
        set { m_objMinValue = value; }
    }

    public string DataType
    {
        get { return m_sDataType; }
        set
        {
            m_sDataType = value.ToUpper();
            //
            if ((btnCalendar != null))
            {
                //Toolbar Textbox
                if (m_objTextBox.Parent.Controls.IsReadOnly)
                {
                    m_objTextBox.Controls.Remove(btnCalendar);
                }
                else
                {
                    m_objTextBox.Parent.Controls.Remove(btnCalendar);
                }
            }
            //
            m_objTextBox.TextAlign = HorizontalAlignment.Left;
            //
            switch (m_sDataType)
            {
                //.ToUpper
                case "NUMBER":
                case "FLOAT":
                case "DOUBLE":
                case "DECIMAL":
                case "MONEY":
                    m_objTextBox.MaxLength = double.MaxValue.ToString().Length;
                    m_objTextBox.TextAlign = HorizontalAlignment.Right;

                    if (m_objMaxValue == null)
                        m_objMaxValue = double.MaxValue;
                    if (m_objMinValue == null)
                        m_objMinValue = double.MinValue;
                    break;
                case "INT":
                case "INTEGER":
                    m_objTextBox.MaxLength = int.MaxValue.ToString().Length;
                    m_objTextBox.TextAlign = HorizontalAlignment.Right;

                    if (m_objMaxValue == null)
                        m_objMaxValue = int.MaxValue;
                    if (m_objMinValue == null)
                        m_objMinValue = int.MinValue;
                    break;
                case "INT64":
                case "LONG":
                case "BIGINT":
                    m_objTextBox.MaxLength = long.MaxValue.ToString().Length;
                    m_objTextBox.TextAlign = HorizontalAlignment.Right;

                    if (m_objMaxValue == null)
                        m_objMaxValue = long.MaxValue;
                    if (m_objMinValue == null)
                        m_objMinValue = long.MinValue;
                    break;
                case "INT16":
                case "SHORT":
                case "SMALLINT":
                    m_objTextBox.MaxLength = short.MaxValue.ToString().Length;
                    m_objTextBox.TextAlign = HorizontalAlignment.Right;

                    if (m_objMaxValue == null)
                        m_objMaxValue = short.MaxValue;
                    if (m_objMinValue == null)
                        m_objMinValue = short.MinValue;
                    break;
                case "DATE":
                case "DATETIME":
                    m_objTextBox.MaxLength = 10;
                    m_objTextBox.CharacterCasing = CharacterCasing.Upper;
                    //
                    if (btnCalendar == null)
                    {
                        btnCalendar = new Button();
                        btnCalendar.Name = m_objTextBox.Name + "_btnCalendar";
                        btnCalendar.Image = Resources.btnCalendar;
                        btnCalendar.Click += btnCalendar_Click;
                    }
                    Init_Button(btnCalendar);
                    //
                    if (!ShowMonthButton)
                    {
                        Button_SetVisible(btnCalendar, false);
                    }
                    break;
                case "DATESHORT":
                    m_objTextBox.MaxLength = 10;
                    m_objTextBox.CharacterCasing = CharacterCasing.Upper;
                    break;
                case "TIME":
                    m_objTextBox.MaxLength = 5;
                    if (m_objMaxValue == null)
                        m_objMaxValue = "23:59";
                    if (m_objMinValue == null)
                        m_objMinValue = "00:00";
                    break;
                case "TIMEEX":
                    m_objTextBox.MaxLength = 6;
                    if (m_objMaxValue == null)
                        m_objMaxValue = "23:59+";
                    if (m_objMinValue == null)
                        m_objMinValue = "00:00-";
                    break;
                case "TEXT":
                case "NTEXT":
                    m_objTextBox.MaxLength = 2000;
                    break;
                default:
                    if (m_sAll_Data_Type.IndexOf(DataType + ",") == -1)
                    {
                        throw new Exception("Invalid data type: " + DataType);
                    }
                    break;
            }
        }
    }

    private string m_sInputPattern;
    public string InputPattern
    {
        get { return m_sInputPattern; }
        set { m_sInputPattern = value; }
    }

    public bool AutoClearError
    {
        get { return m_bClearError; }
        set { m_bClearError = value; }
    }

    public string ControlName
    {
        get { return m_objTextBox.Name; }
    }

    private object _LookupValue;
    public object LookupValue
    {
        get { return _LookupValue; }
        set
        {
            _LookupValue = value;
            if (!_isLookupInvoke && (m_lookupMethod != null))
            {
                CallLookup(LookupMode.GetData);
            }
        }
    }

    private DataRowEx _LookupData;
    public DataRowEx LookupData
    {
        get { return _LookupData; }
        set { _LookupData = value; }
    }

    public string LookupCode
    {
        get { return m_objTextBox.Text; }
        set { m_objTextBox.Text = value; }
    }

    public string LookupName
    {
        get
        {
            if (m_arrControlText == null || m_arrControlText.Length == 0)
            {
                return null;
            }
            else
            {
                return m_arrControlText[0].Text;
            }
        }
        set
        {
            if (m_arrControlText != null && m_arrControlText.Length > 0)
                m_arrControlText[0].Text = value;
        }
    }

    private bool _LookupRequired = true;
    public bool LookupRequired
    {
        get { return _LookupRequired; }
        set { _LookupRequired = value; }
    }

    private bool _ShowMonthButton = true;

    public bool ShowMonthButton
    {
        get { return _ShowMonthButton; }
        set { _ShowMonthButton = value; }
    }


    //--------------
    // Public method
    //--------------

    public TextBoxHandle(TextBox tb, string dataType, object MinValue = null, object MaxValue = null)
    {
        this.m_objTextBox = tb;
        m_objMaxValue = MaxValue;
        m_objMinValue = MinValue;
        this.DataType = dataType.ToUpper();
        //
        if (tb.FindForm() is FormBase)
        {
            m_Form = (FormBase)tb.FindForm();
        }
    }

    private Button m_btnLookup;
    private LookupInvokerEx m_lookupMethod;
    private Control[] m_arrControlText;
    internal void SetLookup(LookupInvokerEx lookupMethod, params Control[] arrControlText)
    {
        m_lookupMethod = lookupMethod;
        if (m_btnLookup == null)
        {
            m_btnLookup = new Button();
            m_btnLookup.Name = m_objTextBox.Name + "_btnLookup";
            m_btnLookup.Image = Resources.btnFind; // 
            
            m_btnLookup.Click += btnLookup_Click;
        }
        //
        Init_Button(m_btnLookup);
        //
        if ((arrControlText != null))
        {
            foreach (Control ctlText in arrControlText)
            {
                if (ctlText is TextBox)
                {
                    FormGlobals.Control_SetViewOnly(ctlText);
                }
                else if (ctlText is Label)
                {
                    FormGlobals.Control_SetStyle(ctlText, FormGlobals.CS_STYLE_INFO);
                }
                ctlText.Text = "";
            }
        }
        //
        m_arrControlText = arrControlText;
        m_dicLookupCache = new Dictionary<string, LookupStructure>();
        //
        this.DataType = "TEXT";
        m_objTextBox.MaxLength = 100;
    }

    internal void ShowLookup()
    {
        CallLookup(LookupMode.SelectData);
    }

    private void CallLookup(LookupMode mode)
    {
        _isLookupInvoke = true;
        try
        {
            if (mode == LookupMode.CheckData)
            {
                if (m_dicLookupCache.ContainsKey(this.LookupCode))
                {
                    this.LookupData = m_dicLookupCache[this.LookupCode].LookupData;
                    mode = LookupMode.CacheData;
                }
            }
            //
            DataRowEx drData = m_lookupMethod.Invoke(this, mode);
            if (mode != LookupMode.SelectData)
                _lastLookupCode = m_objTextBox.Text;
            //
            switch (mode)
            {
                case LookupMode.SelectData:
                    m_objTextBox.Focus();
                    _lastLookupCode = m_objTextBox.Text;
                    break;
                case LookupMode.CheckData:
                case LookupMode.GetData:
                    break;
                //
            }
            if (drData != null && drData.HasData)
            {
                FormGlobals.Control_FillData(m_arrControlText, drData);
            }
            else
            {
                if (m_arrControlText.Length > 1)
                    FormGlobals.Control_ClearData(m_arrControlText);
            }
            if ((this.LookupValue != null) && !m_dicLookupCache.ContainsKey(this.LookupCode))
            {
                LookupStructure lookup = new LookupStructure();
                lookup.LookupValue = this.LookupValue;
                lookup.LookupName = this.LookupName;
                lookup.LookupData = drData;
                m_dicLookupCache.Add(this.LookupCode, lookup);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            _isLookupInvoke = false;
        }
    }
    private Dictionary<string, LookupStructure> m_dicLookupCache;
    private MethodInvoker m_changeMethod;
    public void LookupChanged(MethodInvoker changeMethod)
    {
        m_changeMethod = changeMethod;
    }

    //--------------
    // Private method
    //--------------

    private void Init_Button(Button btn)
    {
        btn.ImageAlign = ContentAlignment.MiddleCenter;
        btn.FlatStyle = FlatStyle.Flat;
        btn.FlatAppearance.BorderSize = 0;
        btn.TabStop = false;
        //Toolbar Textbox
        if (m_objTextBox.Parent.Controls.IsReadOnly)
        {
            btn.Size = new Size(m_objTextBox.Size.Height - 2, m_objTextBox.Size.Height - 2);
            btn.Location = new Point(m_objTextBox.Width - btn.Width - 3, -2);
            if (!m_objTextBox.Controls.ContainsKey(btn.Name))
                m_objTextBox.Controls.Add(btn);
        }
        else
        {
            btn.Size = new Size(m_objTextBox.Size.Height - 4, m_objTextBox.Size.Height - 4);
            btn.Location = new Point(m_objTextBox.Left + m_objTextBox.Width - btn.Width - 2, m_objTextBox.Top + 2);
            if (!m_objTextBox.Parent.Controls.ContainsKey(btn.Name))
                m_objTextBox.Parent.Controls.Add(btn);
        }
        btn.BringToFront();
        btn.Cursor = Cursors.Hand;
        Button_SetVisible(btn);
    }

    private void btnLookup_Click(System.Object sender, System.EventArgs e)
    {
        CallLookup(LookupMode.SelectData);
    }

    private void btnCalendar_Click(System.Object sender, System.EventArgs e)
    {
        Form objForm = m_objTextBox.FindForm();
        string keyName = m_objTextBox.Name;
        if (m_objTextBox.GetType().Name == "ToolStripTextBoxControl")
        {
            object objOwner = Globals.Object_GetPropertyValue(m_objTextBox, "Owner");
            if ((objOwner != null))
                keyName = (string)Globals.Object_GetPropertyValue(objOwner, "Name");
        }
        keyName += "_calendarPopup";
        MonthCalendar calendarPopup = (MonthCalendar)objForm.Controls[keyName];
        if (calendarPopup == null)
        {
            calendarPopup = new MonthCalendar();
            calendarPopup.Name = keyName;
            objForm.Controls.Add(calendarPopup);
            calendarPopup.Visible = false;
            calendarPopup.MaxSelectionCount = 1;
            calendarPopup.BackColor = Color.AliceBlue;
            //
            calendarPopup.DateSelected += Calendar_DateChanged;
            calendarPopup.Leave += Calendar_Leave;
        }
        //
        calendarPopup.Tag = m_objTextBox;
        //
        DateTime dValue = default(DateTime);
        if (Globals.Date_TryParseEx(m_objTextBox.Text,ref dValue))
        {
            calendarPopup.SetDate(dValue);
        }
        //
        Point locationOnForm = objForm.PointToClient(m_objTextBox.Parent.PointToScreen(m_objTextBox.Location));
        //
        calendarPopup.Location = new Point(locationOnForm.X + 1, locationOnForm.Y + m_objTextBox.Height + 1);
        if (calendarPopup.Left + calendarPopup.Width > objForm.Width - 6)
        {
            calendarPopup.Left = locationOnForm.X - (calendarPopup.Width - m_objTextBox.Width);
        }
        if (calendarPopup.Top + calendarPopup.Height > objForm.Height - 6)
        {
            calendarPopup.Top = locationOnForm.Y - (calendarPopup.Height);
        }
        calendarPopup.Visible = true;
        calendarPopup.BringToFront();
        calendarPopup.Focus();
    }

    private void Calendar_DateChanged(object sender, System.Windows.Forms.DateRangeEventArgs e)
    {
        m_objTextBox.Text = e.Start.ToString(Globals.CS_DISPLAY_DATE_FORMAT);
        m_objTextBox.Focus();
    }

    private void Calendar_Leave(object sender, System.EventArgs e)
    {
        ((Control)sender).Visible = false;
    }

    public void DateTime_SetVisibleIcon(bool visible)
    {
        Button_SetVisible(btnCalendar, visible);
    }

    private bool _isFocus;
    private void objTextBox_Enter(object sender, System.EventArgs e)
    {
        try
        {
            _isFocus = true;
            if (m_objTextBox.ReadOnly)
                return;
            switch (m_sDataType.ToUpper())
            {
                case "DATE":
                case "DATETIME":
                    DateTime dValue = default(DateTime);
                    if (Globals.Date_TryParseEx(m_objTextBox.Text,ref dValue))
                    {
                        if (m_objTextBox.Tag != null && !String.IsNullOrEmpty(((FormGlobals.FormControlExt)m_objTextBox.Tag).DataFormat))
                        {
                            m_objTextBox.Text = dValue.ToString(((FormGlobals.FormControlExt)m_objTextBox.Tag).DataFormat);
                        }
                        else
                            m_objTextBox.Text = dValue.ToString(Globals.CS_EDIT_DATE_FORMAT);
                        
                    }
                    else
                    {
                        m_objTextBox.Text = "";
                    }
                    break;
                case "DATESHORT":
                    break;
                case "TIME":
                    string sValue = m_objTextBox.Text.Trim();
                    if (sValue.Length > 0)
                    {
                        Globals.Time_FixString(ref sValue);
                        dValue = default(DateTime);
                        if (Globals.Date_TryParseEx("01/01/00 " + sValue, ref dValue))
                        {
                            m_objTextBox.Text = dValue.ToString(Globals.CS_EDIT_TIME_FORMAT);
                        }
                        else
                        {
                            m_objTextBox.Text = "";
                        }
                    }
                    break;
                case "TIMEEX":
                    sValue = m_objTextBox.Text.Trim();
                    if (sValue.Length > 0)
                    {
                        string sExtend = "";
                        if (sValue.EndsWith("+") || sValue.EndsWith("-"))
                        {
                            sExtend = sValue.Substring(sValue.Length - 1);
                            sValue = sValue.Substring(0, sValue.Length - 1);
                        }
                        Globals.Time_FixString(ref sValue);
                        dValue = default(DateTime);
                        if (Globals.Date_TryParseEx("01/01/00 " + sValue, ref dValue))
                        {
                            m_objTextBox.Text = dValue.ToString(Globals.CS_EDIT_TIME_FORMAT) + sExtend;
                        }
                        else
                        {
                            m_objTextBox.Text = "";
                        }
                    }
                    break;
            }
            m_objTextBox.SelectAll();
            //
            //if ((m_Form != null))
                //Tam thoi an di
                //m_Form.HandleLookup = (m_lookupMethod != null);
            //
        }
        catch (Exception ex)
        {
            FormGlobals.Message_Error(ex);
        }
    }

    private void TextBox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
    {
        try
        {
            if (e.Handled)
                return;

            bool bHandled = false;
            switch ((int)e.KeyChar)
            {
                case 13:
                    //Enter
                    if (!m_objTextBox.Multiline)
                    {
                        e.Handled = true;
                        //objTextBox.FindForm.SelectNextControl(objTextBox, True, True, True, True)
                        //SendKeys.SendWait("{TAB}")
                        return;
                    }
                    break;
                case 8:
                    //Backspace
                    break;
                default:
                    string sValidChar = "0123456789";

                    if (CS_FLOAT_TYPE.Contains(m_sDataType.ToUpper()))
                    {
                        sValidChar += Globals.CS_DIGIT_GROUP_SYMBOL + Globals.CS_DECIMAL_SYMBOL;
                    }
                    else if (CS_INT_TYPE.Contains(m_sDataType.ToUpper()))
                    {
                        sValidChar += Globals.CS_DIGIT_GROUP_SYMBOL;
                    }
                    else if (m_sDataType.ToUpper().Contains("DATE"))
                    {
                        //sValidChar += "/- "
                        sValidChar = "";
                    }
                    else if (m_sDataType.ToUpper() == "TIME")
                    {
                        sValidChar += ":";
                    }
                    else if (m_sDataType.ToUpper() == "TIMEEX")
                    {
                        sValidChar += ":+-";
                    }
                    else
                    {
                        sValidChar = "";
                    }
                    if (!string.IsNullOrEmpty(sValidChar))
                        bHandled = (sValidChar.IndexOf(e.KeyChar) < 0);
                    //
                    if (bHandled)
                    {
                        ShowTip("Invalid character input: " + e.KeyChar);
                    }
                    break;
                //
            }

            e.Handled = bHandled;

        }
        catch (Exception ex)
        {
            //Throw ex
            FormGlobals.Message_Error(ex);
        }
    }

    private void ShowTip(string sTip)
    {
        ToolTip objToolTip = FormGlobals.Form_GetToolTip(m_objTextBox.FindForm());
        objToolTip.ToolTipTitle = "";
        objToolTip.Show(sTip, m_objTextBox, 1000);
    }

    private void objTextBox_MouseEnter(object sender, System.EventArgs e)
    {
        m_bMouseOver = true;
        if (Debugger.IsAttached)
            SetToolTip(false);
    }

    private void SetToolTip(bool bShow)
    {
        if (m_objTextBox.ReadOnly == true || m_objTextBox.Enabled == false)
            return;
        ToolTip objToolTip = FormGlobals.Form_GetToolTip(m_objTextBox.FindForm());
        //
        objToolTip.Active = false;
        objToolTip.Hide(m_objTextBox);
        //
        string sText = string.Format("Input Length: {0}/{1}" + Globals.vbCr, m_objTextBox.Text.Length, m_objTextBox.MaxLength);
        if (FormGlobals.Control_GetRequired(m_objTextBox))
        {
            sText += "Require: Yes";
            objToolTip.ToolTipIcon = ToolTipIcon.Warning;
        }
        else
        {
            sText += "Require: No";
            objToolTip.ToolTipIcon = ToolTipIcon.Info;
        }
        //
        if (CS_FLOAT_TYPE.Contains(m_sDataType))
        {
            objToolTip.ToolTipTitle = "Data type: Number";
        }
        else if (CS_INT_TYPE.Contains(m_sDataType))
        {
            objToolTip.ToolTipTitle = "Data type: Integer";
        }
        else if (CS_TIME_TYPE.Contains(m_sDataType))
        {
            objToolTip.ToolTipTitle = "Data type: Time";
        }
        else if (CS_DATE_TYPE.Contains(m_sDataType))
        {
            objToolTip.ToolTipTitle = "Data type: Date";
        }
        else
        {
            objToolTip.ToolTipTitle = "Data type: String";
        }
        //
        objToolTip.SetToolTip(m_objTextBox, sText);
        objToolTip.Active = true;
        //
        if (bShow)
        {
            objToolTip.Show(sText, m_objTextBox, objToolTip.AutoPopDelay);

        }
        else
        {
        }
        //
        //Return objToolTip
    }

    private void objTextBox_MouseLeave(object sender, System.EventArgs e)
    {
        m_bMouseOver = false;
    }

    private void objTextBox_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
    {
        if ((m_lookupMethod != null) && e.KeyData == FormGlobals.CS_LOOKUP_KEY && m_btnLookup.Visible)
        {
            CallLookup(LookupMode.SelectData);
        }
    }

    private bool _isLookupInvoke;

    private string _lastLookupCode = Guid.NewGuid().ToString();
    private void objTextBox_TextChanged(object sender, System.EventArgs e)
    {
        FormGlobals.Control_SetError(m_objTextBox as Control, "");
        if (!_isFocus && !string.IsNullOrEmpty(m_objTextBox.Text))
        {
            if (CS_INT_TYPE.Contains(m_sDataType) && !string.IsNullOrEmpty(m_objTextBox.Text))
            {
                if (m_objTextBox.MaxLength == 4)
                {
                    m_objTextBox.Text = m_objTextBox.Text.Replace(Globals.CS_DIGIT_GROUP_SYMBOL, "");
                }
            }
            if (m_sNumber_Data_Type.Contains(m_sDataType) && m_objTextBox.MaxLength > 4 && !m_objTextBox.Text.Contains(Globals.CS_DIGIT_GROUP_SYMBOL))
            {
                string sFormat = FormGlobals.TextBox_GetFormat(m_objTextBox);
                if (sFormat == null)
                {
                    if (FormGlobals.TextBox_GetScale(m_objTextBox) == 0)
                    {
                        sFormat = Globals.CS_DISPLAY_NUMBER_FORMAT;
                    }
                    else
                    {
                        sFormat = "#,##0." + new string('0', (int)FormGlobals.TextBox_GetScale(m_objTextBox));
                    }
                }
                m_objTextBox.Text = Globals.Object_SetValueEx<decimal>(m_objTextBox.Text).ToString(sFormat);
            }
        }
    }

    private void m_objTextBox_LostFocus(object sender, System.EventArgs e)
    {
        //If _isFocus And TypeName(m_objTextBox) = "ToolStripTextBoxControl" Then
        if (m_objTextBox.GetType().Name == "ToolStripTextBoxControl")
        {
            if ((m_lookupMethod != null) & m_objTextBox.Text != _lastLookupCode)
                FormGlobals.Control_ForceValidate(m_objTextBox);
        }
    }


    private bool m_validateLookup;
    private void TextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
    {
        try
        {
            _isFocus = false;
            if (m_Form != null)
                //--tam an
                //m_Form.HandleLookup = false;
            if (m_objTextBox.ReadOnly || m_validateLookup)
                return;

            string sValue = m_objTextBox.Text.Trim();
            m_objTextBox.Text = sValue;
            //
            if ((m_lookupMethod != null) & m_objTextBox.Text != _lastLookupCode)
            {
                m_validateLookup = true;
                CallLookup(LookupMode.CheckData);
                if (this.LookupValue == null && !string.IsNullOrEmpty(sValue))
                {
                    if (_LookupRequired)
                    {
                        e.Cancel = true;
                        CallLookup(LookupMode.SelectData);
                        if (this.LookupValue == null)
                        {
                            sValue = "";
                            m_objTextBox.Text = "";
                        }
                    }
                    else
                    {
                        m_objTextBox.Text = sValue;
                    }
                }
                //
                return;
            }
            //
            bool bWrong = false;
            string sMessage = null;

            //Check valid data type
            if (sValue.Length > 0)
            {
                if (CS_STRING_TYPE.IndexOf(m_sDataType.ToUpper() + ",") > -1)
                {
                    if (!string.IsNullOrEmpty(FormGlobals.Control_GetError(m_objTextBox)))
                    {
                        return;
                    }
                    else
                    {
                        m_objTextBox.Text = sValue;
                    }
                }
                //Check data type
                if (CS_FLOAT_TYPE.Contains(m_sDataType))
                {
                    bWrong = !Globals.IsNumeric(sValue) && !Globals.IsDecimal(sValue);
                    sMessage = FormGlobals.CS_INPUT_NUMERIC;
                }
                else if (CS_INT_TYPE.Contains(m_sDataType))
                {
                    bWrong = !Globals.IsNumeric(sValue);
                    if (!bWrong)
                    {
                        long iValue = 0;
                        iValue = Globals.Object_SetValueEx<int>(sValue);
                        //Globals.Object_SetValue(sValue, ref iValue);
                        m_objTextBox.Text = iValue.ToString();
                        //Long.Parse(sValue)
                    }
                    sMessage = FormGlobals.CS_INPUT_INTEGER;
                }
                else if ("DATE;DATETIME".Contains(m_sDataType))
                {
                    bool shortDate = ((FormGlobals.FormControlExt)m_objTextBox.Tag).DataFormat == Globals.CS_EDIT_MONTHYEAR_FORMAT; //nhập tháng năm
                    Globals.Date_FixString(ref sValue,shortDate);
                    System.DateTime mDate = default(System.DateTime);
                    if (!Globals.Date_TryParseEx(sValue, ref mDate))
                    {
                        bWrong = true;
                    }
                    else
                    {
                        //Object_SetValue(sValue, mDate)
                        if (shortDate)
                            m_objTextBox.Text = mDate.ToString(Globals.CS_EDIT_MONTHYEAR_FORMAT);
                        else
                            m_objTextBox.Text = mDate.ToString(Globals.CS_DISPLAY_DATE_FORMAT);
                        //CType(sValue, Date).ToString(cstDisplayDateFormat)
                    }
                    sMessage = FormGlobals.CS_INPUT_DATE;
                }
                else if (m_sDataType == "TIME")
                {
                    Globals.Time_FixString(ref sValue);
                    if (!Globals.IsDate(ref sValue))
                    {
                        bWrong = true;
                    }
                    else
                    {
                        m_objTextBox.Text = DateTime.Parse(sValue).ToString(Globals.CS_DISPLAY_TIME_FORMAT);
                    }
                    sMessage = FormGlobals.CS_INPUT_TIME;
                }
                else if (m_sDataType == "TIMEEX")
                {
                    string sExtend = "";
                    if (sValue.EndsWith("+") || sValue.EndsWith("-"))
                    {
                        sExtend = sValue.Substring(sValue.Length - 1);
                        sValue = sValue.Substring(0, sValue.Length - 1);
                    }
                    Globals.Time_FixString(ref sValue);
                    if (!Globals.IsDate(ref sValue))
                    {
                        bWrong = true;
                    }
                    else
                    {
                        m_objTextBox.Text = DateTime.Parse(sValue).ToString(Globals.CS_DISPLAY_TIME_FORMAT) + sExtend;
                    }
                    sValue = m_objTextBox.Text;
                    sMessage = FormGlobals.CS_INPUT_TIME;
                }
                else if (m_sDataType == "EMAIL")
                {
                    if (!Globals.String_IsValidEmail(sValue))
                    {
                        bWrong = true;
                        sMessage = FormGlobals.CS_INPUT_EMAIL;
                    }
                }
                else if (m_sDataType == "WEB")
                {
                    if (!Globals.String_IsValidWeb(sValue))
                    {
                        bWrong = true;
                        sMessage = FormGlobals.CS_INPUT_WEB;
                    }
                }
                else if (m_sDataType == "REGEX")
                {
                    if (!Regex.IsMatch(sValue, m_sInputPattern))
                    {
                        bWrong = true;
                        sMessage = string.Format(FormGlobals.CS_INPUT_REGEX, m_sInputPattern);
                    }
                }
                else
                {
                    return;
                }
                //Check range
                if (!(m_objMinValue == null & m_objMaxValue == null))
                {
                    object sCheckRange = CheckRange(sValue, m_sDataType);
                    //, m_objMinValue, m_objMaxValue)
                    if (!bWrong)
                    {
                        bWrong = !string.IsNullOrEmpty(sCheckRange.ToString());
                    }
                    sMessage += sCheckRange.ToString();
                }

                if (m_bClearError & bWrong)
                {
                    //Auto clear error
                    m_objTextBox.Text = "";
                    return;
                }
                //Check required
            }
            else
            {
                //If Control_GetRequire(objTextBox) Then
                //    sMessage = "Please input required value"
                //    bWrong = True
                //End If
            }

            if (bWrong)
            {
                e.Cancel = true;
            }
            else
            {
                sMessage = "";
                if (m_objMinValue is TextBox)
                    FormGlobals.Control_SetError((TextBox)m_objMinValue, "");
                if (m_objMaxValue is TextBox)
                    FormGlobals.Control_SetError((TextBox)m_objMaxValue, "");
                //
                // Auto format for numeric value
                if (m_sNumber_Data_Type.Contains(m_sDataType) & !string.IsNullOrEmpty(m_objTextBox.Text))
                {
                    decimal mValue = default(decimal);
                    
                    //Globals.Object_SetValue(m_objTextBox.Text, ref mValue);
                    mValue = Globals.Object_SetValueEx<Decimal>(m_objTextBox.Text);

                    //m_objTextBox.Text = Globals.FormatNumberEx(mValue, FormGlobals.Control_GetExtension(m_objTextBox).DataScale);
                    if (CS_INT_TYPE.Contains(m_sDataType) && m_objTextBox.MaxLength == 4)
                    {
                        m_objTextBox.Text = m_objTextBox.Text.Replace(Globals.CS_DIGIT_GROUP_SYMBOL, "");
                    }
                }
            }

            FormGlobals.Control_SetError(m_objTextBox, sMessage);
        }
        catch (Exception ex)
        {
            //Throw
            FormGlobals.Message_Error(ex);
        }
        finally
        {
            m_validateLookup = false;
        }
    }

    //Hàm kiểm tra khoảng nhập dữ liệu (private)
    private object CheckRange(string sValue, string sDataType)
    {
        //, Optional ByVal objMinValue As Object = Nothing, Optional ByVal objMaxValue As Object = Nothing) As String
        bool bReturn = true;
        string sMinValue = null;
        string sMaxValue = null;

        switch (sDataType.ToUpper())
        {
            case "DECIMAL":
            case "MONEY":
            case "NUMBER":
            case "FLOAT":
            case "DOUBLE":
            case "LONG":
            case "BIGINT":
            case "INT":
            case "INTEGER":
            case "SHORT":
            case "SMALLINT":
            case "INT64":
            case "INT32":
            case "INT16":
                object MaxValue = null;
                object MinValue = null;
                object mValue = null;

                switch (sDataType.ToUpper())
                {
                    case "NUMBER":
                    case "FLOAT":
                    case "DOUBLE":
                    case "DECIMAL":
                    case "MONEY":
                        MaxValue = Convert.ToDecimal(MaxValue);
                        MinValue = Convert.ToDecimal(MinValue);
                        mValue = Convert.ToDecimal(mValue);
                        break;
                    case "LONG":
                    case "BIGINT":
                    case "INT64":
                        MaxValue = Convert.ToInt64(MaxValue);
                        MinValue = Convert.ToInt64(MinValue);
                        mValue = Convert.ToInt64(mValue);
                        break;
                    case "INT":
                    case "INTEGER":
                    case "INT32":
                        MaxValue = Convert.ToInt32(MaxValue);
                        MinValue = Convert.ToInt32(MinValue);
                        mValue = Convert.ToInt32(mValue);
                        break;
                    case "SHORT":
                    case "SMALLINT":
                    case "INT16":
                        MaxValue = Convert.ToInt16(MaxValue);
                        MinValue = Convert.ToInt16(MinValue);
                        mValue = Convert.ToInt16(mValue);
                        break;
                }

                if (m_objMaxValue is Control)
                {
                    MaxValue = FormGlobals.Control_GetValue((Control)m_objMaxValue, sDataType);
                }
                else
                {
                    Globals.Object_SetValue(m_objMaxValue, ref MaxValue);
                }

                if (m_objMinValue is Control)
                {
                    MinValue = FormGlobals.Control_GetValue((Control)m_objMinValue, sDataType);
                }
                else
                {
                    Globals.Object_SetValue(m_objMinValue, ref MinValue);
                }

                if (!Null.IsNull(MaxValue))
                {
                    sMaxValue = MaxValue.ToString();
                }
                if (!Null.IsNull(MinValue))
                {
                    sMinValue = MinValue.ToString();
                }

                if (Globals.IsNumeric(sValue))
                {
                    Globals.Object_SetValue(sValue, ref mValue);
                    if (!Null.IsNull(MaxValue))
                    {
                        bReturn = bReturn & Convert.ToDouble(mValue) <= Convert.ToDouble(MaxValue);
                    }
                    if (!Null.IsNull(MinValue))
                    {
                        bReturn = bReturn & Convert.ToDouble(mValue) >= Convert.ToDouble(MinValue);
                    }
                }
                else
                {
                    bReturn = false;
                }
                break;
            case "DATE":
            case "DATETIME":
                MaxValue = default(System.DateTime);
                if (m_objMaxValue is Control)
                {
                    MaxValue = FormGlobals.Control_GetValue<System.DateTime>((Control)m_objMaxValue);
                }
                else
                {
                    Globals.Object_SetValue(m_objMaxValue, ref MaxValue);
                }

                if ((DateTime)MaxValue == Null.NullDate)
                {
                    GetValue(true, ref MaxValue);
                }

                MinValue = default(System.DateTime);
                if (m_objMinValue is Control)
                {
                    MinValue = FormGlobals.Control_GetValue<System.DateTime>((Control)m_objMinValue);
                }
                else
                {
                    Globals.Object_SetValue(m_objMinValue, ref MinValue);
                }

                if ((DateTime)MinValue == Null.NullDate)
                {
                    GetValue(false, ref MinValue);
                }

                if ((DateTime)MinValue == Null.NullDate)
                    MinValue = Null.MIN_DATE;
                if ((DateTime)MaxValue == Null.NullDate)
                    MaxValue = Null.MAX_DATE;

                if ((DateTime)MaxValue > Null.NullDate)
                {
                    sMaxValue = ((DateTime)MaxValue).ToString(Globals.CS_DISPLAY_DATE_FORMAT);
                }
                if ((DateTime)MinValue > Null.NullDate)
                {
                    sMinValue = ((DateTime)MinValue).ToString(Globals.CS_DISPLAY_DATE_FORMAT);
                }

                System.DateTime dValue = default(System.DateTime);
                if (Globals.Date_TryParseEx(sValue, ref dValue))
                {
                    if ((DateTime)MaxValue > Null.NullDate)
                    {
                        bReturn = bReturn & dValue <= (DateTime)MaxValue;
                    }
                    if ((DateTime)MinValue > Null.NullDate)
                    {
                        bReturn = bReturn & dValue >= (DateTime)MinValue;
                    }
                }
                else
                {
                    bReturn = false;
                }
                break;
            case "TIME":
            case "TIMEEX":
                string sTemp = null;
                MaxValue = default(DateTime);
                if (m_objMaxValue is Control)
                {
                    sTemp = FormGlobals.Control_GetValue<string>((Control)m_objMaxValue);
                }
                else
                {
                    sTemp = m_objMaxValue.ToString();
                }
                MaxValue = Globals.Time_ParseEx(DateTime.Today, sTemp);
                MinValue = default(DateTime);
                if (m_objMinValue is Control)
                {
                    sTemp = FormGlobals.Control_GetValue<string>((Control)m_objMinValue);
                }
                else
                {
                    sTemp = m_objMinValue.ToString();
                }
                MinValue =  Globals.Time_ParseEx(DateTime.Today, sTemp);

                if ((DateTime)MaxValue > Null.NullDate)
                {
                    sMaxValue = Globals.Time_ToStringEx(DateTime.Today, (DateTime)MaxValue);
                }
                if ((DateTime)MinValue > Null.NullDate)
                {
                    sMinValue = Globals.Time_ToStringEx(DateTime.Today, (DateTime)MinValue);
                }
                DateTime CurrentValue = Globals.Time_ParseEx(DateTime.Today,  sValue);
                if (CurrentValue > Null.NullDate)
                {
                    if ((DateTime)MaxValue > Null.NullDate)
                    {
                        bReturn = bReturn & CurrentValue <= (DateTime)MaxValue;
                    }
                    if ((DateTime)MinValue > Null.NullDate)
                    {
                        bReturn = bReturn & CurrentValue >= (DateTime)MinValue;
                    }
                }
                else
                {
                    bReturn = false;
                }
                break;
            default:
                break;
        }
        string sMessage = "";
        if (!bReturn)
        {
            if (!string.IsNullOrEmpty(sMinValue) & !string.IsNullOrEmpty(sMaxValue))
            {
                sMessage = " from " + sMinValue + " to " + sMaxValue;
            }
            else if (!string.IsNullOrEmpty(sMinValue))
            {
                sMessage = " greate than or equal " + sMinValue;
            }
            else if (!string.IsNullOrEmpty(sMaxValue))
            {
                sMessage = " less than or equal " + sMaxValue;
            }
        }
        return sMessage;
    }



    private void GetValue(bool isMaxValue, ref object mValue)
    {
        object objValue = null;
        if (isMaxValue)
        {
            objValue = m_objMaxValue;
        }
        else
        {
            objValue = m_objMinValue;
        }
        if (objValue is TextBox)
        {
            object tmpObject = objValue;
            while (tmpObject is TextBox)
            {
                if (((TextBox)tmpObject).Tag is FormGlobals.FormControlExt)
                {
                    TextBoxHandle mHandle = (TextBoxHandle)((FormGlobals.FormControlExt)((TextBox)tmpObject).Tag).HandleObject;
                    if (isMaxValue)
                    {
                        tmpObject = mHandle.MaxValue;
                    }
                    else
                    {
                        tmpObject = mHandle.MinValue;
                    }
                    if (tmpObject is Control)
                    {
                        FormGlobals.Control_SetValue((Control)tmpObject, mValue);
                    }
                    else
                    {
                        Globals.Object_SetValue(tmpObject, ref mValue);
                    }
                    if (!Null.IsNull(mValue))
                        break; // TODO: might not be correct. Was : Exit While
                }
                else
                {
                    break; // TODO: might not be correct. Was : Exit While
                }
            }
        }
    }

    public void SetButtonVisible(bool visible)
    {
        btnCalendar.Visible = visible;
    }

    private void objTextBox_VisibleChanged(object sender, System.EventArgs e)
    {
        if ((btnCalendar != null))
            Button_SetVisible(btnCalendar);
        if ((m_btnLookup != null))
            Button_SetVisible(m_btnLookup);
    }

    private void m_objTextBox_ReadOnlyChanged(object sender, System.EventArgs e)
    {
        if ((btnCalendar != null))
            Button_SetVisible(btnCalendar);
        if ((m_btnLookup != null))
            Button_SetVisible(m_btnLookup);
    }

    private void m_objTextBox_EnabledChanged(object sender, System.EventArgs e)
    {
        if ((btnCalendar != null))
            Button_SetVisible(btnCalendar);
        if ((m_btnLookup != null))
            Button_SetVisible(m_btnLookup);
    }

    private void Button_SetVisible(Button btn)
    {
        btn.Visible = (m_objTextBox.Visible && !m_objTextBox.ReadOnly && m_objTextBox.Enabled);
    }

    private void Button_SetVisible(Button btn, bool visible)
    {
        btn.Parent.Controls.Remove(btn);
    }

    private void m_objTextBox_LocationChanged(object sender, System.EventArgs e)
    {
        if (btnCalendar != null)
            Init_Button(btnCalendar);
        if (m_btnLookup != null)
            Init_Button(m_btnLookup);
    }

    //----------

}
